<!DOCTYPE html>
<!--
{{ if show_details }}
    {{ if host }}Host: {{ host }}{{ end }}
    {{ if original_uri }}Original URI: {{ original_uri }}{{ end }}
    {{ if forwarded_for }}Forwarded for: {{ forwarded_for }}{{ end }}
    {{ if namespace }}Namespace: {{ namespace }}{{ end }}
    {{ if ingress_name }}Ingress name: {{ ingress_name }}{{ end }}
    {{ if service_name }}Service name: {{ service_name }}{{ end }}
    {{ if service_port }}Service port: {{ service_port }}{{ end }}
    {{ if request_id }}Request ID: {{ request_id }}{{ end }}
    Timestamp: {{ nowUnix }}
{{ end }}
-->
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="robots" content="nofollow,noarchive,noindex">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- {{ if or (eq code 408) (eq code 425) (eq code 429) (eq code 500) (eq code 502) (eq code 503) (eq code 504) }} -->
  <meta http-equiv="refresh" content="30">
  <!-- {{ end }} -->
  <meta name="title" content="{{ code }}: {{ message | escape }}">
  <meta name="description" content="{{ description | escape }}">
  <meta property="og:title" content="{{ code }}: {{ message | escape }}">
  <meta property="og:description" content="{{ description | escape }}">
  <meta property="twitter:title" content="{{ code }}: {{ message | escape }}">
  <meta property="twitter:description" content="{{ description | escape }}">
  <title>{{ code }}: {{ message }}</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      min-height: 100%;
      height: 100%;
      width: 100%;
      background-color: #111;
      color: #333;
      overflow: hidden;
      font-family: sans-serif;
      font-size: 20px;
      word-break: keep-all;
    }

    canvas {
      z-index: 1;
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
    }

    .frame {
      z-index: 3;
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      background: radial-gradient(ellipse at center, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, .2) 19%, rgba(0, 0, 0, .9) 100%);
    }

    @keyframes horizontalLine {
      0% {
        top: -25%;
      }
      100% {
        top: 100%;
      }
    }

    .frame div {
      position: absolute;
      left: 0;
      top: -25%;
      width: 100%;
      height: 20%;
      background-color: rgba(0, 0, 0, .12);
      box-shadow: 0 0 30px rgba(0, 0, 0, .25);
      transform: rotate(2deg);
      animation: horizontalLine 12s linear infinite;
    }

    .frame div:nth-child(1) {
      animation-delay: 0ms;
    }

    .frame div:nth-child(2) {
      animation-delay: 4s;
    }

    .frame div:nth-child(3) {
      animation-delay: 8s;
    }

    .container-center {
      height: 100%;
      align-items: center;
      display: flex;
      justify-content: center;
    }

    .container-center div {
      z-index: 2;
    }

    h1, h2 {
      text-align: center;
      color: transparent;
      text-shadow: 0 0 10px rgba(0, 0, 0, .6);
    }

    @keyframes codeText {
      0% {
        text-shadow: 0 0 15px rgba(0, 0, 0, .3);
      }
      33% {
        text-shadow: 0 0 5px rgba(0, 0, 0, .2);
      }
      66% {
        text-shadow: 0 0 10px rgba(0, 0, 0, .1);
      }
      100% {
        text-shadow: 0 0 15px rgba(0, 0, 0, .3);
      }
    }

    h1 {
      font: bold 13em Arial, sans-serif;
      animation: codeText 2s linear infinite;
      margin: 0;
    }

    @keyframes descriptionText {
      0% {
        text-shadow: 0 0 10px rgba(0, 0, 0, .5)
      }
      33% {
        text-shadow: 0 0 5px rgba(0, 0, 0, .1)
      }
      66% {
        text-shadow: 0 0 5px rgba(0, 0, 0, .25)
      }
      100% {
        text-shadow: 0 0 10px rgba(0, 0, 0, .5)
      }
    }

    h2 {
      font: bold 2.5em Arial, sans-serif;
      animation: descriptionText 4s linear infinite;
      margin-bottom: 0;
    }
  </style>
</head>
<body>

<div class="container-center">
  <div>
    <h1>{{code}}</h1>
    <h2 data-l10n>{{ description }}</h2>
  </div>
</div>

<div class="frame">
  <div></div>
  <div></div>
  <div></div>
</div>

<canvas id="canvas"></canvas>

<script>
  // main idea author: https://codepen.io/moklick
  const $canvas = document.getElementById('canvas');
  const width = Math.max(800, document.body.clientWidth);
  const height = Math.max(600, document.body.clientHeight);

  $canvas.width = width;
  $canvas.height = height;

  const ctx = $canvas.getContext('2d');

  ctx.fillStyle = '#404040';
  ctx.fillRect(0, 0, width, height);
  ctx.fill();

  const imgData = ctx.getImageData(0, 0, width, height)
  const onScreen = imgData.data;

  // allocate a peace of memory to fill with random color
  const pixelsBuffToRepeat = new Uint8ClampedArray(Math.min(onScreen.length, 1024 * 32));

  // fill the buffer with random grayscale colors
  for (let i = 0; i < pixelsBuffToRepeat.length; i += 4) {
    const color = Math.floor((Math.random() * 255) + 50);

    pixelsBuffToRepeat[i] = color; // R value
    pixelsBuffToRepeat[i + 1] = color; // G value
    pixelsBuffToRepeat[i + 2] = color; // B value
    pixelsBuffToRepeat[i + 3] = 255; // A value
  }

  // prevent the redraw function from running multiple times at the same time
  let redrawMutex = false;

  const redraw = () => {
    if (redrawMutex) {
      return;
    }

    redrawMutex = true;

    const dstLen = onScreen.length;
    let pos = 0;

    do {
      // pick a random length of bytes to copy from the source slice in range [0...buff.length] with the step of 4
      let takeLen = Math.floor(Math.random() * pixelsBuffToRepeat.length / 4) * 4;

      // if picked length is greater than the remaining space in the onScreen, adjust it
      if (pos + takeLen > dstLen) {
        takeLen = dstLen - pos;
      }

      // copy the random length of bytes from the buffer to the onScreen
      onScreen.set(pixelsBuffToRepeat.slice(0, takeLen), pos);

      // move the position in the onScreen to the next random position
      pos += takeLen;
    } while (pos < dstLen)

    ctx.putImageData(imgData, 0, 0);

    queueMicrotask(() => {
      redrawMutex = false
    });
  };

  redraw(); // draw the noise first time

  const redrawFrequency = 45; // redraw the noise every 45ms
  /** @type {Number|undefined} */
  let flickerInterval = window.setInterval(redraw, redrawFrequency);

  // stop drawing when the tab is hidden
  // https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilitychange_event
  window.addEventListener('visibilitychange', () => {
    if (document.hidden && flickerInterval !== undefined) {
      window.clearInterval(flickerInterval);
      flickerInterval = undefined;
    } else if (!document.hidden && flickerInterval === undefined) {
      flickerInterval = window.setInterval(redraw, redrawFrequency);
    }
  });
</script>

<!-- {{- if l10n_enabled -}} -->
<script>// {{ l10nScript }}</script>
<!-- {{- end -}} -->
</body>
</html>
